package cn.amossun.starter.mybatis.data.security.core;

import cn.hutool.core.collection.CollectionUtil;
import cn.amossun.starter.common.util.ClassUtil;
import cn.amossun.starter.mybatis.data.security.cache.LocalCache;
import cn.amossun.starter.mybatis.data.security.properties.ResultConfiguration;
import cn.amossun.starter.mybatis.data.security.properties.ResultMapConfiguration;
import cn.amossun.starter.mybatis.data.security.rule.MybatisDecryptRule;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.Field;
import java.util.*;

/**
 * @description: 解密属性
 * @author: Amos.Sun
 * @DateTime: 2020/03/10 18:53
 **/
@Slf4j
@Data
@AllArgsConstructor
public class FieldConditionContext {

    //解密对象
    private Object parameterObject;

    //Mybatis解密对象规则
    private MybatisDecryptRule mybatisDecryptRule;

    /**
     * 获取解密属性含多级属性
     * @return
     */
    public List<Field> getDecryptFields() throws Exception {
        List<Field> mapFieldList = LocalCache.getObjectFiledCache(parameterObject.getClass().getName());
        if(CollectionUtil.isNotEmpty(mapFieldList)) {
            return mapFieldList;
        }
        List<Field> resultFieldList = buildDecryptFields();
        LocalCache.updateObjectFiledCache(parameterObject.getClass().getName(), resultFieldList);
        return resultFieldList;
    }

    public List<Field> buildDecryptFields() throws Exception {
        //获取解密对象属性
        List<Field> objectFieldList = ClassUtil.getAllClassFields(parameterObject.getClass());
        //解密对象属性是否为空
        if(CollectionUtil.isEmpty(objectFieldList)) {
            return null;
        }
        List<Field> rootFieldList = getDecryptFields(parameterObject.getClass());
        List<Field> resultFieldList = new ArrayList<>(CollectionUtil.isNotEmpty(rootFieldList) ? rootFieldList.size() + objectFieldList.size() : objectFieldList.size());
        if(CollectionUtil.isNotEmpty(rootFieldList)) {
            resultFieldList.addAll(rootFieldList);
        }
        //获取Orm配置中对象属性集合
        for(Field childField : objectFieldList) {
            Class clazz = childField.getType().getClass();
            //判断是否为jdk基本类型
            if (ClassUtil.isPrimitive(clazz)) {
                continue;
            }

            ResultMapConfiguration resultMapConfiguration = mybatisDecryptRule.getDecryptRuleMap().get(clazz.getName());
            //判断当前参数对象是否需解密处理
            if(resultMapConfiguration == null || CollectionUtil.isEmpty(resultMapConfiguration.getPropertyMap())) {
                continue;
            }
            resultFieldList.add(childField);
        }
        return resultFieldList;
    }

    protected List<Field> getDecryptFields(Class<?> getClass) throws Exception {
        //获取解密对象属性
        List<Field> classFieldList = ClassUtil.getAllClassFields(getClass);
        //解密对象属性是否为空
        if(CollectionUtil.isEmpty(classFieldList)) {
            return null;
        }
        String className = getClass.getName();
        ResultMapConfiguration resultMapConfiguration = mybatisDecryptRule.getDecryptRuleMap().get(className);
        //判断当前参数对象是否需解密处理
        if(resultMapConfiguration == null || CollectionUtil.isEmpty(resultMapConfiguration.getPropertyMap())) {
            return null;
        }
        //获取Orm配置中对象属性集合
        Map<String, ResultConfiguration> propertyMap = resultMapConfiguration.getPropertyMap();
        List<Field> resultFieldList = new ArrayList<>(resultMapConfiguration.getPropertyMap().size());
        for(Field field : classFieldList) {
            //判断当前属性是否需解密
            if(!propertyMap.containsKey(field.getName())) {
                continue;
            }
            ResultConfiguration resultConfiguration = propertyMap.get(field.getName());
            if(resultConfiguration.isDecrypt()) {
                resultFieldList.add(field);
            }
        }
        return resultFieldList;
    }


}
